package cn.cimoc.handler;


import cn.cimoc.model.vo.ResultVO;
import cn.cimoc.annotation.ResponseResult;
import cn.cimoc.util.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.LinkedHashMap;
import java.util.Objects;

/**
 * @author LGZ
 * @date 2021/7/5 14:01
 * <p>
 * 若控制器或方法加了{@code @ResponseResult}注解
 * 自动对返回数据进行处理
 * 原理可见我的博客：https://cimoc.cn/2021/10/28/springboot-Automatic-encapsulation-of-returned-data/
 */
@Slf4j
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {

    public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        ServletRequestAttributes sra = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        assert sra != null;
        HttpServletRequest request = sra.getRequest();
        ResponseResult responseResult = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
        return responseResult != null;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (o instanceof ResultVO) {
            return o;
        } else if (o instanceof LinkedHashMap) {
            HttpServletResponse httpServletResponse = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
            LinkedHashMap r = (LinkedHashMap) o;
            if (r.containsKey("status") && r.containsKey("error")) {
                log.error(r.toString());
                assert httpServletResponse != null;
                httpServletResponse.setStatus(500);
                return CommonUtils.ajaxReturn((int)r.get("status"), r.get("error").toString());
            }
        }
        return CommonUtils.ajaxReturn(o);
    }
}
